package com.github.baichuan.binary;


/**
 * 字节数据编码模式
 */
public enum Endian {
    /**
     * 大端
     */
    BIG,
    /**
     * 小端
     */
    LITTLE;

    /**
     * 将数字转换成相应编码的字节数组
     * @param value
     * @return
     */
    public byte[] bytes(long value){
        byte[] bytes = new byte[8];
        for(int i = 0; i< 8; i++){
            int offset = 64 - (i + 1) * 8;
            bytes[i] = (byte)((value >> offset) &  0xFF);
        }
        if(this == BIG){
            return bytes;
        }
        else{
            return Bytes.of(bytes).reverse().bytes();
        }
    }

    public long uint64(byte[] bytes){
        if (bytes.length != 8) {
            throw new IllegalArgumentException("expected byte[8] but byte[" + bytes.length + "]");
        }

        if (this == LITTLE) {
            bytes = Bytes.of(bytes).reverse().bytes();
        }

        long result = 0;
        result += ((long) uint8(bytes[0]) << 7 * 8);
        result += ((long) uint8(bytes[1]) << 6 * 8);
        result += ((long) uint8(bytes[2]) << 5 * 8);
        result += ((long) uint8(bytes[3]) << 4 * 8);
        result += ((long) uint8(bytes[4]) << 3 * 8);
        result += ((long) uint8(bytes[5]) << 2 * 8);
        result += ((long) uint8(bytes[6]) << 1 * 8);
        result += uint8(bytes[7]);
        return result;
    }

    public long uint32(byte[] bytes){
        if (bytes.length != 4) {
            throw new IllegalArgumentException("expected byte[4] but byte[" + bytes.length + "]");
        }

        if (this == Endian.LITTLE) {
            bytes = Bytes.of(bytes).reverse().bytes();
        }

        long result = 0;
        result += ((long)uint8(bytes[0]) << 24);
        result += ((long)uint8(bytes[1]) << 16);
        result += (uint8(bytes[2]) << 8);
        result += uint8(bytes[3]);
        return result;
    }


    public int uint16(byte[] bytes){
        if (bytes.length != 2) {
            throw new IllegalArgumentException("expected byte[2] but byte[" + bytes.length + "]");
        }

        if (this == Endian.LITTLE) {
            bytes = Bytes.of(bytes).reverse().bytes();
        }

        return (uint8(bytes[0]) << 8) + uint8(bytes[1]);
    }

    public short uint8(byte b){
        return (short) (b & 0xFF);
    }
}
